package lol.clann.minecraft.springboot.api.utils;

import org.springframework.core.Ordered;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.function.Consumer;

/**
 * 封装TransactionAspectSupport和TransactionSynchronizationManager,减少样板代码
 *
 * @author pyz
 * @date 2019/8/8 9:53 AM
 */
public class TransactionUtils {

    public static void registerSuspendListener(Runnable callback) {
        registerSuspendListener(Ordered.LOWEST_PRECEDENCE, callback);
    }

    public static void registerSuspendListener(int order, Runnable callback) {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public int getOrder() {
                return order;
            }

            @Override
            public void suspend() {
                callback.run();
            }
        });
    }

    public static void registerResumeListener(Runnable callback) {
        registerResumeListener(Ordered.LOWEST_PRECEDENCE, callback);
    }

    public static void registerResumeListener(int order, Runnable callback) {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public int getOrder() {
                return order;
            }

            @Override
            public void resume() {
                callback.run();
            }
        });
    }

    public static void registerFlushListener(Runnable callback) {
        registerFlushListener(Ordered.LOWEST_PRECEDENCE, callback);
    }

    public static void registerFlushListener(int order, Runnable callback) {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public int getOrder() {
                return order;
            }

            @Override
            public void flush() {
                callback.run();
            }
        });
    }


    public static void registerBeforeCommitListener(Consumer<Boolean> callback) {
        registerBeforeCommitListener(Ordered.LOWEST_PRECEDENCE, callback);
    }

    public static void registerBeforeCommitListener(int order, Consumer<Boolean> callback) {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public int getOrder() {
                return order;
            }

            @Override
            public void beforeCommit(boolean readOnly) {
                callback.accept(readOnly);
            }
        });
    }


    public static void registerAfterCommitListener(Runnable callback) {
        registerAfterCommitListener(Ordered.LOWEST_PRECEDENCE, callback);
    }

    public static void registerAfterCommitListener(int order, Runnable callback) {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public int getOrder() {
                return order;
            }

            @Override
            public void afterCommit() {
                callback.run();
            }
        });
    }


    public static void registerBeforeCompletionListener(Runnable callback) {
        registerBeforeCompletionListener(Ordered.LOWEST_PRECEDENCE, callback);
    }

    public static void registerBeforeCompletionListener(int order, Runnable callback) {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public int getOrder() {
                return order;
            }

            @Override
            public void beforeCompletion() {
                callback.run();
            }
        });
    }


    public static void registerAfterCompletionListener(Consumer<Integer> callback) {
        registerAfterCompletionListener(Ordered.LOWEST_PRECEDENCE, callback);
    }

    public static void registerAfterCompletionListener(int order, Consumer<Integer> callback) {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public int getOrder() {
                return order;
            }

            @Override
            public void afterCompletion(int status) {
                callback.accept(status);
            }
        });
    }


    public static void setRollbackOnly() {
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }

    public static void flush() {
        TransactionAspectSupport.currentTransactionStatus().flush();
    }

    public static boolean hasSavepoint() {
        return TransactionAspectSupport.currentTransactionStatus().hasSavepoint();
    }

    public static boolean isCompleted() {
        return TransactionAspectSupport.currentTransactionStatus().isCompleted();
    }

    public static boolean isNewTransaction() {
        return TransactionAspectSupport.currentTransactionStatus().isNewTransaction();
    }

    public static boolean isRollbackOnly() {
        return TransactionAspectSupport.currentTransactionStatus().isRollbackOnly();
    }

    public static Object createSavepoint() {
        return TransactionAspectSupport.currentTransactionStatus().createSavepoint();
    }

    public static void releaseSavepoint(Object savepoint) {
        TransactionAspectSupport.currentTransactionStatus().releaseSavepoint(savepoint);
    }

    public static void rollbackToSavepoint(Object savepoint) {
        TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savepoint);
    }


}
